package com.example.myutil;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.SerializationUtils;

public class MyUtil {
	private static final Logger LOG = LoggerFactory.getLogger(MyUtil.class);
	public static final byte POSITION_CODE_PROVINCE = 1;
	public static final byte POSITION_CODE_CITY = 2;
	public static final byte POSITION_CODE_COUNTY = 3;
	public static final byte POSITION_CODE_TOWN = 4;
	public static final byte POSITION_CODE_VILLAGE = 5;
	
	public static final int DEFAULT_PAGE_SIZE = 10; 
	
	public static final String RESOURCES_PATH = "/resources/agrithings";
	public static final String IMGS_PATH = RESOURCES_PATH + "/images";
	public static final String PEST_IMG_PATH = IMGS_PATH + "/pest";
	public static final String AVATAR_PATH = IMGS_PATH + "/avatar";
	public static final String FORMULA_IMG_PATH = IMGS_PATH + "/formula";
	public static final String TASK_IMG_PATH = IMGS_PATH + "/task";
	public static final String STORE_IMG_PATH = IMGS_PATH + "/store";	
	public static final String GPS_MULFILE_PATH = RESOURCES_PATH + "/GPS";
	
	public static final String DEFAULT_PATH = RESOURCES_PATH +"/file";
	/**
	 * app安装包路径
	 */
	public static final String APP_PATH = RESOURCES_PATH+"/app";
	
	/**
	 * ueditor编辑器上传文件路径
	 */
	public static final String UEDITOR_PATH = RESOURCES_PATH+"/ueditor";
	
	
	private static DateConvert convert = new DateConvert();
	
	public static boolean isNullString(String str){
		return null == str || str.trim().length() == 0;
	}
	
	public static boolean notNullString(String str){
		return !isNullString(str);
	}
	
	public static final String dateTime2Str(Date dateTime){
		return DateUtils.date2Str(dateTime, DateUtils.datetimeFormat);
	}
	
	//
	public static final String getFullPosCode(String posCode){
		
		if(isNullString(posCode)) return null;
		
		posCode = posCode.replace(" ", ""); //去掉所有空格
		
		//行政区划代码 规则：AABBCCDDDEEE共12位
		posCode = posCode.replaceAll("^(0+)", ""); //去除前面0
		
		posCode = (posCode.length()<12)?
				posCode.concat(getZeroStr(12-posCode.length())):posCode;
		
		return posCode;
	}
	
	/*
	 * 将区划代码末尾0去掉，然后根据长度就近补齐为2/4/6/9/12位，如果去0后是8位，则补0为9位
	 */
	public static final String getShortestPosCode(String posCode){
		if(isNullString(posCode)) return null;
		posCode = posCode.replace(" ", ""); //去掉所有空格
		
		posCode = posCode.replaceAll("^(0+)", ""); //去除前面0
		posCode = posCode.replaceAll("(0+)$", ""); //去除后面0
		
		if(posCode.length() == 0) return null;
		
		if(posCode.length() == 1){
			posCode += "0";//补0变2位
		}
		else if(posCode.length() == 3){
			posCode += "0";//补0变4位
		}
		else if(posCode.length() == 5){
			posCode += "0";//补0变6位
		}
		else if(posCode.length() > 6 && posCode.length() < 9){
			posCode += getZeroStr(9 - posCode.length());//补0变9位
		}
		else if(posCode.length() > 9 && posCode.length() < 12){
			posCode += getZeroStr(12 - posCode.length());//补0变12位
		}
		if(posCode.length() > 12) posCode = posCode.substring(0, 12);
		return posCode;
	}
	
	public static final long getPosCodeRangeMin(String posCode){
		String code = getFullPosCode(posCode);
		if(null == code) return 0;
		
		return Long.valueOf(code);
	}
	
	public static final long getPosCodeRangeMax(String posCode){
		if(isNullString(posCode)) return 0;
		try{
			posCode = getShortestPosCode(posCode);
			long code = Long.valueOf(posCode);
			++code;
			
			posCode = getFullPosCode(code+"");
			return Long.valueOf(posCode);
		}catch(NumberFormatException ex){
			LOG.error("", ex);
			return 0;
		}
		
	}
	
	public static final byte getPosCodeLevel(String posCode){
		if(isNullString(posCode)) return Byte.MAX_VALUE;
		
		posCode = getShortestPosCode(posCode);
		byte posCodeLevel = POSITION_CODE_PROVINCE;
		switch(posCode.length()){
			case 4:
			{
				posCodeLevel = POSITION_CODE_CITY;
				break;
			}
			case 6:
			{
				posCodeLevel = POSITION_CODE_COUNTY;
				break;
			}
			case 9:
			{
				posCodeLevel = POSITION_CODE_TOWN;
				break;
			}
			case 12:
			{
				posCodeLevel = POSITION_CODE_VILLAGE;
				break;
			}
		}
		return posCodeLevel;
	}
	
	public static final byte getPosCodeNextLevel(String posCode){
		byte posCodeLevel = getPosCodeLevel(posCode);
		return (posCodeLevel < POSITION_CODE_VILLAGE)?
				++posCodeLevel:posCodeLevel;
	}
	
	/*
	 * 获取全0字符串，例如：len为3，则返回"000"
	 */
	public static final String getZeroStr(int len){
		if(len <= 0) return "";
		String str = "0";
		while(--len > 0) str += "0";
		return str;
	}
	
	public static final String[] str2Array(String str){
		if(isNullString(str)) return null;
		
		return str2Array(str, ",");
	}
	
	public static final String[] str2Array(String str, String splitor){
		if(splitor == null || splitor == "") splitor = ",";
		
		if(isNullString(str)) return null;
		str = str.trim();
		
		if(!str.contains(splitor)) return new String[]{str};
		
		return str.split(splitor);
	}
	
	public static final String array2Str(String[] array){
		return array2Str(array, ",");
	}
	
	public static final String collection2Str(Collection<String> c){
		return collection2Str(c, ",");
	}
	
	public static final String collection2Str(Collection<String> c, String splitor){
		if(c == null || c.isEmpty()) return null;
		if(splitor == null) splitor = ",";
		
		String str = null;
		for(String item : c){
			if(isNullString(item)) continue;
			if(str == null){
				str = item;
			}
			else{
				str += "," + item;
			}
		}
		return str;
	}
	
	public static final String array2Str(String[] array, String splitor){
		if(array == null || array.length == 0) return null;
		if(splitor == null) splitor = ",";
		String result = null;
		for(String str : array){
			if(MyUtil.notNullString(str)){
				if(result == null){
					result = str;
				}
				else{
					result += (splitor + str);
				}
			}
		}
		return result;
	}
	
	public static final String getWebappsPath(HttpServletRequest request){
		return getWebappsPath(request.getSession());
	}
	
	public static final String getWebappsPath(HttpSession session){
		String path = session.getServletContext().getRealPath("");
		int pos = path.lastIndexOf("/"); 
		if(pos == -1) pos = path.lastIndexOf("\\");//windows下目录是"\"
		if(pos != -1)
			path = path.substring(0, pos);
		return path;
	}
	
	public static final String getFileSuffix(String fileName){
		if(MyUtil.isNullString(fileName)) return "";
		fileName = fileName.trim();
		
		int pos = fileName.lastIndexOf(".");
		
		return (pos == -1)? "":fileName.substring(pos);
		
	}
	
	public static String getBase64ImageSuffix(String str){
		if(MyUtil.isNullString(str)) return "";
		//data:image/jpeg;base64,
		final String flag = "image/";
		int pos1 = str.indexOf(flag);
		int pos2 = (pos1 != -1)? str.indexOf(";", pos1) : -1;
		
		return (pos1 != -1 && pos2 != -1)? str.substring(pos1+flag.length(), pos2).trim() : "";
	}
	
	/**
	 * 是否是数字
	 * @param str
	 * @return
	 */
	public static final boolean isNumeric(String str){
	   if(MyUtil.isNullString(str)) return false;
	   str = str.trim();
	   Pattern pattern = Pattern.compile("[0-9]*"); 
	   Matcher isNum = pattern.matcher(str);
	   if( !isNum.matches() ){
	       return false; 
	   } 
	   return true; 
	}
	
	/**
	 * 是否是数值，包含小数、负数
	 * @param str
	 * @return
	 */
	public static final boolean isNumValue(String str){
		if(MyUtil.isNullString(str)) return false;
		   str = str.trim();
		   Pattern pattern = Pattern.compile("^((-?[1-9]\\d*)|(-?[1-9]\\d*\\.\\d+)|(-?0\\.\\d*[1-9])|(-?[0])|(-?[0]\\.\\d+))$"); 
		   Matcher isNum = pattern.matcher(str);
		   if( !isNum.matches() ){
		       return false; 
		   } 
		   return true; 
	}
	
	//103°58'30.99"
	public static final double getGpsValue(String str){
		if(MyUtil.isNullString(str)) return Double.MAX_VALUE;
		str = str.trim();
		
		int pos1 = str.indexOf("°");
		int pos2 = str.indexOf("'");
		int pos3 = str.indexOf("\"");
		
		double du = 0;
		double fen = 0;
		double miao = 0;
		
		if(pos1 == -1){
			return getCustomGpsValue(str);
		}
		else{
			du = Double.valueOf(str.substring(0, pos1));
		}
		
		if(pos1 != -1 && pos2 != -1){
			fen = Double.valueOf(str.substring(pos1+1, pos2));
		}
		
		if(pos2 != -1 && pos3 != -1){
			miao = Double.valueOf(str.substring(pos2+1, pos3));
		}
		
		return (du + (fen*1.0)/60 + (miao*1.0/3600));
	}
	
	// 可能是 1034770.3 dddffmm.m  也可能是ddd.dddd
	private static double getCustomGpsValue(String gps){
		gps = gps.trim();
		int dotPos = gps.indexOf(".");
		if(dotPos >= 5 || (dotPos == -1 && gps.length() >= 5)){//dddffmm.m 
			if(dotPos == -1) dotPos = gps.length();
			String mm = gps.substring(dotPos-2);
			String ff = gps.substring(dotPos-4, dotPos-2);
			String ddd = gps.substring(0, dotPos-4);
			return Double.valueOf(ddd) + (Double.valueOf(ff)*1.0/60) + (Double.valueOf(mm)*1.0/3600);
		}
		else{
			return Double.valueOf(gps);
		}
	}
	
	//拆分关键字去重
	public static String[] splitKeyWords(String words, String splittor){
		if(MyUtil.isNullString(words)) return null;
		words = words.trim();
		
		String[] arry = words.split(splittor);
		
		if(arry == null || arry.length == 0) return null;
		
		HashSet<String> wordSet = new HashSet<String>();
		for(String w : arry){
			if(MyUtil.notNullString(w))
				wordSet.add(w.trim());
		}
		String[] result = new String[wordSet.size()];
		Iterator<String> iter = wordSet.iterator();
		int indx = 0;
		while(iter.hasNext()){
			result[indx++] = iter.next();
		}
		return result;
	}
	
	public static  int calcCurrPlantingStage(int period, Date startPlantingDate){
		Date now = new Date();
		if(period <=0 || startPlantingDate == null || startPlantingDate.after(now)){
			return 1;
		}
		int month = calcMonthDiff(startPlantingDate, now);
		month = month > (period*12)? (period*12):(month+1);
		return month;
	}
	
	// 得到2个日期的月份差
	public static int calcMonthDiff(Date start, Date end) {
		if (start.after(end)) {
			Date t = start;
			start = end;
			end = t;
		}
		Calendar startCalendar = Calendar.getInstance();
		startCalendar.setTime(start);
		Calendar endCalendar = Calendar.getInstance();
		endCalendar.setTime(end);
		Calendar temp = Calendar.getInstance();
		temp.setTime(end);
		temp.add(Calendar.DATE, 1);

		int year = endCalendar.get(Calendar.YEAR) - startCalendar.get(Calendar.YEAR);
		int month = endCalendar.get(Calendar.MONTH) - startCalendar.get(Calendar.MONTH);
		int day = endCalendar.get(Calendar.DAY_OF_MONTH) - startCalendar.get(Calendar.DAY_OF_MONTH);
		if(day < 0) month = month - 1;
		return year * 12 + month;
	}
	
	public static final boolean isInWenShan(long code){
		return (code >= 532601000000L && code < 532702000000L);
	}
	
	
	public static final String getRandomString(int length) {
		length = (length < 0)?0:length;
	    String base = "abcdefghijklmnopqrstuvwxyz0123456789";     
	    Random random = new Random();     
	    StringBuffer sb = new StringBuffer();     
	    for (int i = 0; i < length; i++) {     
	        int number = random.nextInt(base.length());     
	        sb.append(base.charAt(number));     
	    }     
	    return sb.toString();     
	 }
	
	public static final String getRandomNumStr(int length){
		length = (length < 0)?0:length;
	    String base = "0123456789";     
	    Random random = new Random();     
	    StringBuffer sb = new StringBuffer();     
	    for (int i = 0; i < length; i++) {     
	        int number = random.nextInt(base.length());     
	        sb.append(base.charAt(number));     
	    }     
	    return sb.toString();
	}
	
	public static final String getRandNickName(){
		return "u" + getRandomString(9);
	}
	
	public static final String getRandUserName(){
		return "u" + getRandomNumStr(9);
	}
	
	//判断是否是自动生成的userName
	public static boolean isRandomUserName(String userName){
		if(MyUtil.isNullString(userName)) return false;
		userName = userName.trim();
		if(userName.startsWith("u") && userName.length() == 10){
			if(MyUtil.isNumeric(userName.substring(1))) return true;
		}
		return false;
	}
	
	/**
	 * 去掉中间“-”后的uuid
	 * @return
	 */
	public static final String getUUID(){
		return UUID.randomUUID().toString().replaceAll("-", "");
	}

	public static final Integer toIntSafe(Object str){
		if(str == null || !MyUtil.isNumeric(str.toString())){
			return null;
		}
		try{
			if(str instanceof Integer){
				return (Integer)str;
			}
			else{
				return Integer.valueOf(str.toString().trim());
			}
		}
		catch(Exception e){}
		return null;
	}
	
	public static final Long toLongSafe(Object str){
		if(str == null || !MyUtil.isNumeric(str.toString())){
			return null;
		}
		try{
			return Long.valueOf(str.toString().trim());
		}
		catch(Exception e){}
		return null;
	}
	
	public static final Double toDoubleSafe(Object str){
		if(str == null) return null;
		
		try{
			return Double.valueOf(str.toString().trim());
		}
		catch(Exception e){}
		return null;
	}
	
	public static final String toStringSafe(Object obj){
		if(obj == null) return null;
		
		return obj.toString();
	}
	
	public static final Date toDateSafe(Object obj){
		if(obj == null) return null;
		
		if(obj instanceof Date){
			return (Date)obj;
		}
		else{
			Date date = convert.convert(obj.toString());
			return date;
		}
	}
	
	

	public static BigDecimal toBigDecimal(Object obj){
		try{
			if(obj != null){
				return new BigDecimal(obj.toString());
			}
		}
		catch(Exception e){}
		return null;
	}
	
	
	/**
	 * 处理json中的特殊字符
	 * @param s
	 * @return
	 */
	public static String stringToJson(String s) {
		String result = s;
		if(StringUtils.isNotBlank(s)){
			StringBuffer sb = new StringBuffer();
			for (int i = 0; i < s.length(); i++) {
				char c = s.charAt(i);
				switch (c) {
				case '\"':
					sb.append("\\\"");
					break;
				case '\\':
					sb.append("\\\\");
					break;
				case '/':
					sb.append("\\/");
					break;
				case '\b':
					sb.append("\\b");
					break;
				case '\f':
					sb.append("\\f");
					break;
				case '\n':
					sb.append("<br/>");
					break;
				case '\r':
					sb.append("");
					break;
				case '\t':
					sb.append("\\t");
					break;
				default:
					sb.append(c);
				}
			}
			result = sb.toString();
		}
		return result;
	}

	/**
	 * Set转换成List
	 * @param set
	 * @return
	 */
	public static final <T> List<T> Set2List(Set<T> set){
		
		LinkedList<T> list = new LinkedList<T>();
		if(set != null) list.addAll(set);
		
		return list;
	}
	
	/**
	 * collection转换成List
	 * @param col
	 * @return
	 */
    public static final <T> List<T> collection2List(Collection<T> col){
		
		LinkedList<T> list = new LinkedList<T>();
		if(col != null) list.addAll(col);
		
		return list;
	}
    
    /**
	 * collection转换成Set
	 * @param col
	 * @return
	 */
    public static final <T> Set<T> collection2Set(Collection<T> collection){
		
    	HashSet<T> hashSet = new HashSet<T>();
		if(collection != null) hashSet.addAll(collection);
		
		return hashSet;
	}
    
	/**
	 * 获取数字字符串，如果大于最大值，则返回 最大值+"<sup>+</sup>"
	 * @param number
	 * @param maxNumber
	 * @return
	 */
	public static final String getNumberString(Integer number,Integer maxNumber){
		String result = "0";
		if(number != null){
			if(maxNumber != null && maxNumber.compareTo(number)<0){
				result = String.valueOf(maxNumber)+"<sup>+</sup>";
			}else{
				result = String.valueOf(number);
			}
		}
		return result;
	}
	
	/**
	 * 格式化路径, 把windows路径替换成标准路径
	 * @param input 待格式化的路径
	 * @return 格式化后的路径
	 */
	public static String formatPath(String input) {
		return input.replace( "\\", "/" );
	}
	
	/**
	 * 用户名规则：
	 * 字母开头，
	 * 只允许字母、数字、下划线
	 * 最短5位，最长20位
	 * 存储显示时区分大小写，查询时区分
	 *  mysql字符串比较默认不区分大小写，需要区分时在字段前加binary
	 * @param name
	 * @return
	 */
	public static boolean isUserNameValid(String name){
		if(MyUtil.isNullString(name)) return false;
		name = name.trim();
		
		if(name.length() < 5 || name.length() > 20) return false;
		
		if(name.matches("^[a-zA-Z]+\\w*$")) return true;
		
		return false;
	}
	
	/**
	 * 集合判空
	 * @param c
	 * @return
	 */
	public static boolean isNullCollection(Collection c){
		return c == null || c.isEmpty();
	}
	
	/**
	 * org正式表机构性质数字(1个人种植户  2企业 3合作社 4事业单位)
	 * @param nature
	 * 导入表：个人 公司 单位 合作社
	 * @return
	 */
	public final static Integer getOrgNature(String nature){
		if(MyUtil.isNullString(nature)) return null;
		nature = nature.trim();
		if(MyUtil.isNumeric(nature)){
			return MyUtil.toIntSafe(nature);
		}
		else{
			switch(nature){
			case "个人":  return 1;
			case "公司":  return 2;
			case "合作社": return 3;
			case "单位":  return 4;
			}
			return null;
		}
	}
	
	/**
	 * double值相等判断
	 * @param d1
	 * @param d2
	 * @return
	 */
	public static final boolean DoubleEqual(double d1, double d2){
		return Double.doubleToLongBits(d1) == Double.doubleToLongBits(d2);
	}
	
	public static final boolean isDatetimeString(String str){
		Date date = DateUtils.str2Date(str, DateUtils.datetimeFormat);
		return date != null;
	}
	
	public static final Object deserializeSafe(byte[] obj){
		try{
			return SerializationUtils.deserialize(obj);
		}
		catch(Exception e){
			return null;
		}
	}
}
